﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VentaElectrodomesticos.Contrato;
using System.Reflection;
using System.Data.SqlClient;

namespace VentaElectrodomesticos.Datos
{
    public static class Introspection<T> where T : Entity, new()
    {
        public static Dictionary<String, object> getRunTimeProperties(T entity)
        {
            Dictionary<String, object> properties = new Dictionary<string,object>();
            Type tipo = entity.GetType();
            foreach (PropertyInfo prop in tipo.GetProperties())
            {
                if (!prop.Name.StartsWith("__")) {
                    properties.Add(prop.Name, prop.GetValue(entity, null));
                }
            }
            return properties;
        }

        public static T setPropertiesFromReader(T entity, SqlDataReader reader)
        {
            Type tipo = entity.GetType();
            foreach (PropertyInfo prop in tipo.GetProperties())
            {
                if (!prop.Name.StartsWith("__")) {
                    formatProperty(entity, reader, prop);
                }
            }
            return entity;
        }

        private static void formatProperty(T entity, SqlDataReader reader, PropertyInfo prop)
        {
            object o = reader[prop.Name];
            if (isInteger(o))
            {
                prop.SetValue(entity, formatNullableInteger(o), null);
            }
            else if (isDouble(o))
            {
                prop.SetValue(entity, formatDouble(o), null);
            }
            else if (isDateTime(o))
            {
                prop.SetValue(entity, o.ToString(), null);
            }
            else if (isNotNull(o))
            {
                prop.SetValue(entity, o, null);
            }
        }

        private static Decimal? formatDouble(object o)
        {
            return Convert.ToDecimal(o);
        }

        private static bool isNotNull(object o)
        {
            return o.GetType() != typeof(System.DBNull);
        }

        private static bool isDateTime(object o)
        {
            return o.GetType().IsAssignableFrom(typeof(DateTime));
        }

        private static bool isDouble(object o)
        {
            return o.GetType().IsAssignableFrom(typeof(Double));
        }

        private static bool isInteger(object o)
        {
            return o.GetType().IsAssignableFrom(typeof(int));
        }

        private static int formatNullableInteger(object o)
        {
            int? obj = Convert.ToInt32(o);
            return (obj.HasValue) ? obj.Value : 0;
        }

        public static Type getType(T entity)
        {
            return entity.GetType();
        }
        
    }
}
